defer 中文是推遲的意思,而在函式裡執行 defer 顧名思義就是延遲函式執行的時間,當使用 defer 的函式可以等到父函式結束前一刻才會執行。
範例 1:
package main
import "fmt"
func main() {
fmt.Println("在 defer 函式前印出的字")
defer deferFunc() // 在函式前加入 defer 便會在 main() 函式最後才會執行
fmt.Println("在 defer 函式後印出的字")
}
func deferFunc() {
fmt.Println("我是 defer 函式")
}
範例 1(執行結果):
在 defer 函式前印出的字
在 defer 函式後印出的字
我是 defer 函式
defer 同時也可以使用在匿名函式中:
範例 2:
package main
import "fmt"
func main() {
fmt.Println("在匿名函式前印出的字")
defer func() {
fmt.Println("我是匿名的 defer 函式")
}() // 在匿名函式前加 defer
fmt.Println("在匿名函式後印出的字")
}
範例 2(執行結果):
在匿名函式前印出的字
在匿名函式後印出的字
我是匿名的 defer 函式
通常我們使用 defer 大部分是,釋出資源、關閉開啟檔案、移除程式、清空值,或是也可以將它拿來當處理錯誤的狀況。
這時調皮的我想說那我一次呼叫很多 defer 函式會發生什麼事呢?
範例 3:
package main
import "fmt"
func main() {
fmt.Println("在 defer 函式前印出的字")
defer defer1() // 接收傳回的 addFunc 函式
fmt.Println("在 defer 函式後印出的字")
defer defer2()
defer defer3()
defer defer4()
func() {
fmt.Println("我是 main() 裡的匿名函式")
}()
}
func defer1() {
fmt.Println("我是 defer 函式 1")
}
func defer2() {
fmt.Println("我是 defer 函式 2")
}
func defer3() {
fmt.Println("我是 defer 函式 3")
}
func defer4() {
fmt.Println("我是 defer 函式 4")
}
範例 3(執行結果):
在 defer 函式前印出的字
在 defer 函式後印出的字
我是 main() 裡的匿名函式
我是 defer 函式 4
我是 defer 函式 3
我是 defer 函式 2
我是 defer 函式 1
通過範例我們可以得知若是很多個 defer 會是先進後出的方式呈現,若是比較抽象可以根據下圖來想像,我們將 defer 函式 1~4 一一放進左方的容器,拿出時會從 4 開始拿起。
即使 defer 函式會在父函式的最後才執行,但當 defer 函式有使用到外部變數時,他還是會先取得當下的變數值,然後在最後才執行,也就是說若是在呼叫 defer 值後,又更改變數值,並不會影響先前呼叫 defer 函式的值。
範例 4:
package main
import "fmt"
func main() {
name := "奇犽"
age := 12
defer myFavorite(name, age)
name = "西索"
age = 26
myFavorite(name, age)
}
func myFavorite(name string, age int) {
fmt.Println("我最喜歡的人是:", name, " 他", age, "歲")
}
範例 4(執行結果):
我最喜歡的人是: 西索 他 26 歲
我最喜歡的人是: 奇犽 他 12 歲
根據範例 4 我們得知,雖然 defer 晚執行,但他拿到的變數值依然是原本的 奇犽
。
終於介紹完所有函式 (function),相信大家對於函式有一定的了解了,那我們明天繼續學習在 Go 語言中也不可或缺的 錯誤處理 ,明天見~~